package com.example.util;

import com.example.util.handler.ResultSetHandler;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * @program: sms
 * @description:
 * @author: zhanghz001
 * @create: 2020-11-09 17:35
 **/
public class JDBCTemplate {
    private DataSource dataSource = null;
    private Connection connection = null;
    private PreparedStatement ps = null;
    private ResultSet rs = null;

    public JDBCTemplate(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public int update(String sql, Object... args) {
        int result = 0;
        try {
            connection = dataSource.getConnection();
            //
            ps = connection.prepareStatement(sql);

            //参数源信息
            ParameterMetaData pData = ps.getParameterMetaData();
            //获取sql语句中参数的个数
            int parameterCount = pData.getParameterCount();

            //判断参数个数是否一致
            if (parameterCount != args.length) {
                throw new RuntimeException("参数个数不匹配");

            }

            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
            result = ps.executeUpdate();
            //
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DataSourceUtils.close(connection, ps);
        }
        return result;
    }

    public Long queryForScalar(String sql, ResultSetHandler<Long> rsh, Object... args) {
        Long result = null;
        try {
            connection = DataSourceUtils.getConnection();
            ps = connection.prepareStatement(sql);

            //判断参数数量是否一致
            ParameterMetaData PData = ps.getParameterMetaData();
            int columnCount = PData.getParameterCount();

            if (columnCount != args.length) {
                throw new RuntimeException("参数个数不一致");
            }
            //将字段赋值到预编译中去
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }
            ResultSet rs = ps.executeQuery();

            //
            result = rsh.handler(rs);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DataSourceUtils.close(connection, ps, rs);
        }
        return result;
    }

    public <T> T queryForObject(String sql, ResultSetHandler<T> rsh, Object... args) {
        T result = null;
        try {
            connection = dataSource.getConnection();
            //
            ps = connection.prepareStatement(sql);

            //参数源信息
            ParameterMetaData pData = ps.getParameterMetaData();
            //获取sql语句中参数的个数
            int parameterCount = pData.getParameterCount();

            //判断参数个数是否一致
            if (parameterCount != args.length) {
                throw new RuntimeException("参数个数不匹配");

            }

            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }

            //整理查询结果
            rs = ps.executeQuery();
            result = rsh.handler(rs);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DataSourceUtils.close(connection, ps);
        }
        return result;
    }

    public <T> List<T> queryForList(String sql, ResultSetHandler<T> rsh, Object... args) {
        List<T> result = new ArrayList<>();
        try {
            connection = dataSource.getConnection();
            ps = connection.prepareStatement(sql);
            //校验参数是否一致
            ParameterMetaData pmd = ps.getParameterMetaData();
            int count = pmd.getParameterCount();

            if (count != args.length) {
                throw new RuntimeException("参数个数不一致");
            }

            for (int i = 0; i < args.length; i++) {
                ps.setObject(i + 1, args[i]);
            }

            //查询
            ResultSet rs = ps.executeQuery();
            result = rsh.handler(rs);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DataSourceUtils.close(connection, ps, rs);
        }
        return result;
    }

}
